using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using EntLibContrib.PolicyInjection.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;

namespace EntLibContrib.PolicyInjection.CallHandlers
{
    /// <summary>
    /// An <see cref="ICallHandler"/> that temporarily changes the cursor while the 
    /// next handler is being processed.
    /// </summary>
    [ConfigurationElementType(typeof(CursorCallHandlerData))]
    public class CursorCallHandler : ICallHandler
    {
        private Cursor cursor;

        /// <summary>
        /// Creates a new <see cref="CursorCallHandler"/>.
        /// </summary>
        /// <param name="CursorPolicyName">Cursor.</param>
        public CursorCallHandler(Cursor cursor)
        {
            this.cursor = cursor;
        }

        /// <summary>
        /// Gets the Cursor used by this handler.
        /// </summary>
        /// <value>Cursor.</value>
        public Cursor Cursor
        {
            get { return cursor; }
        }

        #region ICallHandler Members

        /// <summary>
        /// Processes the method call.
        /// </summary>
        /// <remarks>This handler changes the current cursor before the call. Whether or not an exception is thrown, it will
        /// reset the Cursor to its previous value before returning.</remarks>
        /// <param name="input"><see cref="IMethodInvocation"/> with information about the call.</param>
        /// <param name="getNext">delegate to call to get the next handler in the pipeline.</param>
        /// <returns>Return value from the target.</returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn result = null;

            Cursor previousCursor = Cursor.Current;
            Cursor.Current = Cursor;

            try
            {
                result = getNext()(input, getNext);
            }
            finally
            {
                Cursor.Current = previousCursor;
            }

            return result;
        }

        #endregion
    }
}
